/**
 * 
 */
package edu.umd.clip.lm.util;

import java.io.Serializable;
import java.util.*;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 */
public class CompactReadOnlyInt2IntHashMap implements Serializable {
	private static final long serialVersionUID = 1L;

	private final CompactReadOnlyIntHashSet keys;
	private final int values[];
	private final int not_found;
	private final static int DEFAULT_NOT_FOUND = 0;
	
	public CompactReadOnlyInt2IntHashMap(Map<Integer, Integer> map) {
		this(map, CompactReadOnlyIntHashSet.DEFAULT_LOAD_FACTOR);
	}
	public CompactReadOnlyInt2IntHashMap(Map<Integer, Integer> map, float loadFactor) {
		this(map, DEFAULT_NOT_FOUND, loadFactor);
	}
	
	public CompactReadOnlyInt2IntHashMap(Map<Integer, Integer> map, int not_found, float loadFactor) {
		int keys[] = new int[map.size()];
		int pos = 0;
		for(int key : map.keySet()) {
			keys[pos++] = key;
		}
		this.keys = new CompactReadOnlyIntHashSet(keys, loadFactor);
		this.values = new int[keys.length];
		this.not_found = not_found;

		for(Map.Entry<Integer, Integer> e : map.entrySet()) {
			pos = this.keys.getKeyPosition(e.getKey());
			this.values[pos] = e.getValue();
		}
	}
	
	public CompactReadOnlyInt2IntHashMap(int[] keys, int[] values) {
		this(keys, values, DEFAULT_NOT_FOUND, CompactReadOnlyIntHashSet.DEFAULT_LOAD_FACTOR);
	}
	
	public CompactReadOnlyInt2IntHashMap(int[] keys, int[] values, int not_found) {
		this(keys, values, not_found, CompactReadOnlyIntHashSet.DEFAULT_LOAD_FACTOR);
	}
	
	public CompactReadOnlyInt2IntHashMap(int[] keys, int[] values, float loadFactor) {
		this(keys, values, DEFAULT_NOT_FOUND, loadFactor);
	}
	
	public CompactReadOnlyInt2IntHashMap(int[] keys, int[] values, int not_found, float loadFactor) {
		assert(keys.length == values.length);
		
		this.not_found = not_found;
		this.keys = new CompactReadOnlyIntHashSet(keys, loadFactor);
		this.values = new int[values.length];
		for(int i=0; i<keys.length; ++i) {
			int pos = this.keys.getKeyPosition(keys[i]);
			this.values[pos] = values[i]; 
		}
	}
	
	public final int get(int key) {
		int pos = keys.getKeyPosition(key);
		if (pos >= 0) return values[pos];
		return not_found;
	}

	public boolean containsKey(int key) {
		return keys.containsKey(key);
	}

	public final int size() {
		return keys.size();
	}
	
	public HashMap<Integer, Integer> toHashMap() {
		HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(size());
		int keys[] = this.keys.toArray();
		for(int key : keys) {
			int value = get(key);
			map.put(key, value);
		}
		return map;
	}
	
	public int[] keys() {
		return keys.toArray();
	}
	
	public int[] values() {
		return values;
	}
	
	public Iterator iterator() {
		return new Iterator();
	}
	
	public class Iterator {
		private int pos;
		
		private Iterator() {
			pos = -1;
		}
		
		public boolean hasNext() {
			return pos+1 < size(); 
		}
		
		public void next() {
			++pos;
		}
		
		public int key() {
			return keys()[pos];
		}
		
		public int value() {
			return values[pos];
		}
	}
}
